﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Drawing;
using System.Timers;

namespace WcfServiceApplication
{
    [ServiceContract]
    public interface IKalamburyGame
    {
        //USER
        [OperationContract]
        KeyValuePair<CreateUserStaus, User> NewUser(string name);

        [OperationContract]
        void Ialive(User user);

        [OperationContract]
        GameStatus GetStatus(User user);

        [OperationContract]
        List<User> GetUserFromMyRoom(User user);

        [OperationContract]
        void QuitRoom(User user);

        [OperationContract]
        StartedGameStatus StartGame(User user);
        
        //Room
        [OperationContract]
        bool CreateRoom(User user, string name);

        [OperationContract]
        string GetMessages(User user);        

        [OperationContract]
        JoinResult JoinRoom(User user, string roomName);

        [OperationContract]
        bool CheckAnswer(User user, string answer);

        [OperationContract]
        string GetAnswer(User user);

        [OperationContract]
        User GetPainter(User user);

        [OperationContract]
        User WhoWin(User user);

        [OperationContract]
        string GetImage(User user);

        [OperationContract]
        void ResetRoom(User user);

        [OperationContract]
        List<string> GetRoomsNames();

        //Image
        [OperationContract]
        CurrentImage IsNewImage(User user, Guid imageGuid);

        [OperationContract]
        void NewImage(User user, string Image);

        [OperationContract]
        void Clear(string psw);
    }

    [DataContract]
    public class User
    {
        [DataMember]
        internal readonly string Name;
        [DataMember]
        internal int Points = 0;

        internal bool Ready = false;

        private DateTime _LastNotification;
        internal DateTime LastNotification
        {
            get
            {
                return _LastNotification;
            }
            set
            {
                _LastNotification = value;
            }
        }

        internal readonly Guid guid = Guid.NewGuid();

        internal User(string name) 
        {
            this._LastNotification = DateTime.Now;
            this.Name = name;
        }

        internal  void Ialive(){
            _LastNotification = DateTime.Now;
        }  
    }
    [DataContract]
    public enum StartedGameStatus
    {
        [EnumMember]
        Start,
        [EnumMember]
        NotEnoughPlayers,
        [EnumMember]
        WaitingUntilAllPushTheStart
    }
    
    [DataContract]
    public enum GameStatus{
        [EnumMember]
        New,
        [EnumMember]
        Wait,
        [EnumMember]
        During,
        [EnumMember]
        Timeout,
        [EnumMember]
        EndSmbKnown,
        [EnumMember]
        NoRoom
    }

    [DataContract]
    public enum CreateUserStaus
    {
        [EnumMember]
        OK,
        [EnumMember]
        UserExists,
        [EnumMember]
        Fail
    }

    [DataContract]
    public enum JoinResult
    {
        [EnumMember]
        OK,
        [EnumMember]
        ToManyUser,
        [EnumMember]
        AlreadyExists,
        [EnumMember]
        Fail,
    }

    [DataContract]
    public class Room
    {
        [DataMember]
        public string Name { get; set; }

        private static int MAX_COUNT_OF_USERS = 5;
        private static double PLAYING_TIME = 2 * 60 * 1000; //2 min
        private Timer timer;
        private GameStatus _GameStat;

        [DataMember]
        public GameStatus GameStat 
        { 
            get
            {
                return _GameStat;
            }
            set
            {
                if (value == GameStatus.During)
                {
                    timer.Start();
                    timer.Enabled = true;
                }
                else
                {
                    timer.Stop();
                    timer.Enabled = false;
                }
                _GameStat = value;
            } 
        }

        internal DateTime CreationTime { get; set; }
        internal User LastWinner { get; set; }
        internal string CurrentAnswer { get; set; }
        Queue<User> queue = new Queue<User>();
        internal List<User> Users = new List<User>();
        internal User Painter;
        internal CurrentImage CurImage;
        internal string Messages;
        
        private bool Started = false;
        Random rnd = new Random();
        public Room(string name)
        {
            this.timer = new Timer(PLAYING_TIME) {AutoReset = true};
            this.timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            this.Name = name;
            this.GameStat = GameStatus.New;
            this.CurrentAnswer = Answers[rnd.Next(Answers.Count - 1)];
            this.CurImage = new CurrentImage();
            this.CreationTime = DateTime.Now;
            this.Messages = String.Empty;
        }

        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            this.GameStat = GameStatus.Timeout;
            this.AddMessage("", "Timeout ! Answer: " + this.CurrentAnswer);
        }

        private object guard = new object();
        internal void Reset(){
            lock (guard)
            {
                this.GameStat = GameStatus.New;
                this.NextPainter();
                this.SetNewAnswer();
                this.NewImage(ClearImage.ClearImageInString);
                this.SetNoReady();
            }

        }

        internal void SetNewAnswer()
        {
            string oldAnswer = CurrentAnswer;

            do{
                CurrentAnswer = Answers[rnd.Next(Answers.Count - 1)];
            }while(CurrentAnswer == oldAnswer);            
        }

        internal void AddMessage(string userName, string msg)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(Messages);
            sb.AppendLine(String.Format("{0}: {1}", userName, msg));
            Messages = sb.ToString();
        }

        internal string GetMessage()
        {
            return this.Messages;
        }

        internal void AddPoints(User user, int count)
        {
            var u = Users.Where(e => e.Name == user.Name).Select(e => e);
            if(u != null)
                u.First().Points += count;
        }

        internal void NextPainter(){
            User _lastPainter = this.Painter;
            this.Painter = queue.Dequeue();
            queue.Enqueue(_lastPainter);
        }

        internal void RemoveUser(User user){
            if (Users != null){
                foreach (var usr in Users)
                    if (usr.Name == user.Name)
                    {
                        Users.Remove(usr);
                        break;
                    }
            }
        }

        internal JoinResult JoinUser(User user)
        {
            if (Users.Count >= MAX_COUNT_OF_USERS)
                return JoinResult.ToManyUser;
            foreach (var usr in Users)
            {
                if (usr.Name == user.Name)
                    return JoinResult.AlreadyExists;
            }
            
            Users.Add(user);
            if (Painter == null)
                this.Painter = user;
            else
                queue.Enqueue(user);
            
            return JoinResult.OK;
        }

        internal void NewImage(string ImageInString)
        {
            CurImage.Guid = Guid.NewGuid();
            CurImage.ImageInString = ImageInString;
        }

        internal void StartGame()
        {
            GameStat = GameStatus.During;
        }

        internal GameStatus GetStatus()
        {
            return GameStat;
        }

        internal void SetNoReady()
        {
            foreach (User usr in Users)
                usr.Ready = false;
        }

        private static List<string> Answers = new List<string>() {
            "drzewo",
            "kot",
            "pies",
            "słuchawki",
            "myszka",
            "głośniki",
            "bateria",
            "laptop",
            "ładowarka",
            "zasilacz",
            "napój",
            "perfumy",
            "wino",
            "książka",
            "Windows Azure",
            "podkładka pod myszkę",
            "jogurt",
            "telefon komórkowy",
            "mleko",
            "witaminy",
            "wino",
            "portfel"
        };

    }

    internal static class ClearImage
    {
            public static string ClearImageInString = "AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAApxAAAAKJUE5HDQoaCgAAAA1JSERSAAACEwAAAb4IBgAAACnJhokAAAABc1JHQgCuzhzpAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwwAADsMBx2+oZAAAEDxJREFUeF7t0DEBAAAAwqD1T20LL4hAYcCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgw8B8YdvgAAe1BP2MAAAAASUVORK5CYIIL";
    }

    [DataContract]
    public class CurrentImage
    {
        [DataMember]
        public string ImageInString { get; set; }

        [DataMember]
        public Guid Guid { get; set; }

        public CurrentImage()
        {
            ImageInString = String.Empty;
            Guid = Guid.Empty;
        }

    }

  
}
